Repository navigation
fix(plugin-grid): a list row whose click opens nothing draws no record link and no Open item - #33544
objectstack-fleet[bot] wants to merge 7 commits into
Conversation
…k face or Open item Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
…k and no Open item The console hosts (object list, data page, interface list) pass the grid rowOpensRecord: false when the row navigation resolves to none (an authored navigation.mode none, or a list-only object), through ListView. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
…in the row click a plain name cell hands to the row Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pN9UhYM1KGHApVGCH
|
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD Contract reviewServed-tier: Read: card #33317 (body; comments 6880998774 triage, 6885385302 claim, 6886357996 os-dev-report, 6886368569 claim amendment), PR #33544 (body, 14-file list), the net diff ① Derived judgmentsPublic surface (accept-set widening, two published types, nothing removed or narrowed):
Host computations, checked against what each host's row click actually does:
Card acceptance:
Nits (no effect on the contract):
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
|
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD 席位核对Verdict: ACCEPT · head
|
|
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD Landing · head
State: ready + auto-merge. |
Requested by Leehom · project thread
domain:ui#1 · os-project-manager · session_01FEkQ5pN9UhYM1KGHApVGCH
Fixes #33317
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
navigation.mode: 'none',或只开放list的对象),表格第一列不再画成链接(没有链接颜色、下划线、锚点或链接角色),右键菜单也不再出现「打开」和「在新标签页打开」;行操作(如 Revoke)照旧。对象列表、对象数据页、界面列表页三处都生效。rowOpensRecord,不传时行为与之前完全一样,其他宿主不受影响;能打开记录的行(抽屉、页面)不变。回滚即 revert 本 PR。ui/packages/plugin-grid/src/objectGridLinkCell.tsx的opens === false分支;ui/packages/plugin-grid/src/ObjectGrid.tsx的renderRowContextMenu里rowOpensRecord两处;ui/packages/app-shell/src/views/ObjectView.tsx的rowOpensRecord: navOverlay.mode !== 'none'。pnpm --dir ui exec vitest run packages/app-shell/src/views/ObjectView.rowOpensNothing-33317.test.tsx packages/app-shell/src/views/InterfaceListPage.rowOpensNothing-33317.test.tsx,预期 9 个用例全绿。What changes
Measured on
origin/mainf068cde8(#33441 included), through the realObjectView→ListView→ObjectGrid. The console hosts always handListViewanonRowClick, andListViewalways hands the gridonRowClick: navigation.handleClick, so the grid could not tell a row that opens nothing from one that opens a drawer. Two lines decided the face:objectGridGenerateColumns.tsxwraps the first column (and anylink: truecolumn) inLinkCellunconditionally, andRecordLinkinobjectGridLinkCell.tsxdrawsa hrefwhen the host publishes a record URL, elsespan role="link". Measured: a view authorednavigation: { mode: 'none' }on a served object draws the anchor (the host'srecordHrefanswers); a list-only object draws thespan role="link"withdata-testid="primary-field-link"(itsrecordHrefanswersnull).renderRowContextMenuinObjectGrid.tsxreadsconst opens = !!onRowClick || (navigation.mode !== 'none' && ...), so any host handler means Open. Measured: authorednoneoffersrow-context-openandrow-context-open-new-tab; list-only offersrow-context-open.The fix, the narrowest signal the order allowed: the grid cannot derive it from props it already receives (the console's resolved mode never reaches it; the grid branch of
ListViewforwards nonavigation), so one optional prop carries it, absent = today's behaviour.@object-ui/plugin-grid:ObjectGridComponentProps.rowOpensRecord?: boolean.false⇒LinkCell(new internalopensprop) draws the value in a plainspanwith the link's clamp and width only (no anchor, norole, no handler of its own, so its click falls through to the row), andrenderRowContextMenuoffers neither Open nor Open in new tab. Row actions, the actions column and fix(plugin-grid): fold a row's inline primary action into its menu while the table overflows with it #33441's inline fold are untouched.@object-ui/plugin-list:ListViewProps.rowOpensRecord?: boolean, forwarded to the grid only, on the grid's host channel besiderecordLinkAdornment(only when defined).@object-ui/app-shell(ships in@object-ui/console):ObjectViewpassesnavOverlay.mode !== 'none'(the resolved mode:nonefor authorednoneand for a list-only object viaservesRecordRead) throughuseObjectViewListRenderer;ObjectDataPagepassesrecordServed;InterfaceListPagepassesrecordAction !== 'none'.onRowClickis passed exactly as before.rowOpensRecordsections inui/packages/plugin-grid/README.md,content/docs/frontend/plugins/plugin-grid.mdxandui/packages/plugin-list/README.md..changeset/33317-row-opens-nothing-plain.md:@object-ui/plugin-grid,@object-ui/plugin-list,@object-ui/app-shell,@object-ui/consolepatch, both declaration lines.Not changed:
packages/spec, any server package,onRowClickrouting, row actions.Tests
ui/packages/app-shell/src/views/ObjectView.rowOpensNothing-33317.test.tsx, realObjectView+ListViewgrid +MePermissionsProvider, one differential per case (same object and rows; only the view'snavigationor the served operations differ). The right-click menu is opened by acontextmenuevent on a plain cell.navigation.mode: none: the name cell holds noa[href]and no[role="link"], noprimary-field-link; the menu has no Open items and keeps Revoke.none: a ⌘-click on a plain cell still reaches the host (onewindow.open), and a ⌘-click on the now-plain name cell reaches the row too (a second one).page: the name cell is the link, the menu offers Open.ui/packages/app-shell/src/views/InterfaceListPage.rowOpensNothing-33317.test.tsx, realInterfaceListPage+ListViewgrid:recordAction: 'none'→ plain name cell; CONTROL default drawer → link.Red-first (the measurement): the eight production files restored to base
f068cde8(0 differ from base after restore), the new pins kept.base sources: 5 failed | 4 passed (9); restored: 0 bytes differ from HEAD
The ⌘-click case's first half (a plain cell, one
window.open) passed on base: the host's row routing is unchanged; only the name cell's own anchor swallowed the second click. The CONTROL cases passed on both trees.Ablations (
scripts/ablation-replace.mjs, each anchor 1 → 0, restored to the HEAD blob withgit diff HEADempty; ui vitest aliases@object-ui/*tosrc/, so no dist is in the path):six legs, each red, each restored
Acceptance notes
yes (widening). The order allowed a new optional prop when the grid cannot derive the signal; it needed one onObjectGridand one onListView(the hop between the console and the grid), both published, both optional, absent = unchanged. The claim started atno; the seat amends it.ui/packages/plugin-list/src/ListView.tsx(forwarding only) and three docs files are outside the claim's named files; they are the props that carry the signal to the grid, and the docs-driven rule inui/AGENTS.md(Coding Standards, rule 2) asks for the README and docs page.nonerow still opens a new tab. That isuseNavigationOverlay's modifier-click rule ("regardless of the configured navigation mode"), reached through the host'sonRowClick; the order says not to break what the host routes through it, so it stays, and the pin holds it. The menu's "Open in new tab" is gone for such a row, so the two now differ; a list-only row opens no tab either way.nonelist keep their pointer; only the grid is handedrowOpensRecord. Observed by reading, not measured; noted, not filed.preventNavigationon the console object list: the console'shandleRowClickwrites?recordId=for adrawerview without readingpreventNavigation, sorowOpensRecordis keyed to the resolved mode only. Observed by reading, not measured; noted, not filed.eslinton the touched files: 0 errors; theListViewforwarding line adds onereact-hooks/refswarning of the same shape its three siblingviewComponentSchema.type === 'object-grid'lines already carry.Verification
Head
a02d289c(origin/main811b976amerged in; no overlap with this diff). Local subset fromnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, reconciled with--ran:69 derived, 69 run, all exit 0; --ran: 0 NOT-MEASURED, 0 UNRUN
Also run locally, all exit 0 under the verify lock:
pnpm --filter @object-ui/plugin-grid run type-check,@object-ui/plugin-listand@object-ui/app-shell(eachtsc --noEmit && tsc -p tsconfig.test.json, so the new tests are type-checked);pnpm --dir ui exec vitest run packages/plugin-grid/→ 281 files, 2436 passed;packages/plugin-list/→ 173 files, 1856 passed; the app-shellObjectView*,objectView*,InterfaceListPage*andObjectDataPage*files → 111 files, 986 passed; the two new pin files plusObjectView.listOnlyRecordPage-33219androwContextMenu-28434on the final head → 4 files, 36 passed.pnpm --dir ui check:new-line-citations→ 0 new. The full app-shell suite and every other family are CI's.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses. (touched files linted, 0 errors; the repo-wide run is CI's)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code